(function () {
  const generateRender = function (ast) {
    const code = genElement(getRenderTree(ast));
    return 'with(this){return ' + code + '}';
  };
  const getRenderTree = function ({ type, tag, text, attrs, children}) {
    return {
      type,
      tag,
      text: parseText(text),
      attrs: parseAttrs(attrs),
      children: children.map(x => getRenderTree(x))
    };
  };
  const tagRE = /\{\{(.+?)\}\}/g;
  const parseText = function (text) {
    if (!text) return;
    if (!tagRE.test(text)) {
      return JSON.stringify(text);
    }
    tagRE.lastIndex = 0;
    const tokens = [];
    let lastIndex = 0;
    let match;
    let index;
    let tokenValue;
    while ((match = tagRE.exec(text))) {
      index = match.index;
      if (index > lastIndex) {
        tokenValue = text.slice(lastIndex, index);
        tokens.push(JSON.stringify(tokenValue));
      }
      tokens.push(match[1].trim());
      lastIndex = index + match[0].length;
    }
    if (lastIndex < text.length) {
      tokenValue = text.slice(lastIndex)
      tokens.push(JSON.stringify(tokenValue));
    }
    return tokens.join('+');
  };
  const parseAttrs = function (attrs) {
    const attrsStr = attrs.map((pair) => {
      const [k, v] = pair;
      if (k.indexOf('v-') === 0) {
        if (k.indexOf('v-on') === 0) {
          return `'${k}': ${parseHandler(v)}`;
        } else {
          return `'${k}': ${parseText(v)}`;
        }
      } else {
        return `'${k}': ${parseText(v)}`;
      }
    }).join(',')
    return `{${attrsStr}}`;
  };
  const parseHandler = function (handler) {
    console.log(handler, /^\w+$/.test(handler));
    if (/^\w+$/.test(handler)) return handler;
    return `function($event){${handler}}`;
  };
  /**
   * 参考：
   * with(this){return _c('div',{staticClass:"outer"},[_c('div',{staticClass:"inner",on:{"click":function($event){onClick($event, 1)}}},[_v("abc")]),_c('div',{staticClass:"inner",class:{ active: isActive },on:{"click":onClick}},[_v("1"+_s(name)+"2")])])}
   */

  const genElement = function (el) {
    if (el.type === ASTElementType.NORMAL) {
      if (el.children.length) {
        const childrenStr = el.children.map(c => genElement(c)).join(',');
        return `_c('${el.tag}', ${el.attrs}, [${childrenStr}])`;
      }
      return `_c('${el.tag}', ${el.attrs})`;
    } else if (el.type === ASTElementType.PLAINTEXT) {
      return `_v(${el.text})`; // TODO
    }
  };

  window.generateRender = generateRender;
})();